<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.17">
<title>C++ 笔记</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<style>
/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:"\201C" "\201D" "\2018" "\2019"}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
ul.square{list-style-type:square}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre>code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:"[";padding:0 3px 0 2px}
b.button::after{content:"]";padding:0 2px 0 3px}
p a>code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:"\00a0\2013\00a0"}
#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:"\00a0|\00a0"}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:"\00a0"}
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc>ul{margin-left:.125em}
#toc ul.sectlevel0>li>a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2>ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc>:first-child{margin-top:0}
#content #toc>:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details>summary::-webkit-details-marker{display:none}
details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock>table td.icon{text-align:center;width:80px}
.admonitionblock>table td.icon img{max-width:none}
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.exampleblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child{margin-bottom:0}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock>:first-child{margin-top:0}
.sidebarblock>:last-child{margin-bottom:0}
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock>.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock>.content>:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all>*>tr>*{border-width:1px}
table.grid-cols>*>tr>*{border-width:0 1px}
table.grid-rows>*>tr>*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}
table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}
table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}
table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}
table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock>code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li>p:empty:only-child::before{content:"";display:inline-block}
ul.checklist>li>p:first-child{margin-left:-1em}
ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline>li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist>table,.colist>table{border:0;background:none}
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock>.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon>.fa{cursor:default}
a span.icon>.fa{cursor:inherit}
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:" (" attr(title) ")"}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
</style>
</head>
<body class="book">
<div id="header">
<h1>C++ 笔记</h1>
</div>
<div id="content">
<div class="sect1">
<h2 id="_c_编程范式">1. C++ 编程范式</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li>
<p><strong>面向对象编程（Object Oriented Programming，OOP）</strong>
面向对象编程以对象为中心，将问题抽象为一系列对象，并通过对象之间的交互来实现功能。
在 C++ 中，面向对象编程通常使用类和对象来实现，包括类/对象、继承、动态绑定、方法改写、对象替换等机制。</p>
</li>
<li>
<p><strong>泛型编程（Generic Programming，GP）</strong>
泛型编程以类型为中心，允许编写可以适用于多种数据类型的通用代码。
C++ 中的模板编程是实现泛型编程的一种方式，通过定义模板函数和模板类，可以在编译时根据实际类型进行实例化，从而实现代码的复用和通用性。</p>
</li>
<li>
<p><strong>面向过程编程（Procedure Oriented Programming，POP）</strong>
这种范式将问题分解为一系列步骤，第一步做什么，第二步做什么，&#8230;&#8203;&#8230;&#8203;，然后用函数把这些步骤一步一步实现，使用的时候一个一个依次调用就可以了。</p>
</li>
<li>
<p><strong>面向函数编程</strong>
C 也支持函数式编程范式，尽管它不像一些纯函数式编程语言（如 Haskell 或 Erlang）那样完全基于函数式编程。在 C 中，可以使用 Lambda 表达式和算法库（如 STL）来实现函数式编程的一些特性，如高阶函数、不可变性和递归等。</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>这些编程范式并不是相互独立的，而是可以相互结合使用的。在实际的软件开发中，通常会根据具体的需求和场景选择适合的编程范式或混合使用多种范式。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_c_数据类型">2. C++ 数据类型</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_指针">2.1. 指针</h3>
<div class="sect3">
<h4 id="_智能指针">2.1.1. 智能指针</h4>
<div class="paragraph">
<p>C 中引入智能指针(smart pointer)的主要目的是为了解决动态内存管理的问题（C不像Java等语言有垃圾回收机制GC，C++对性能要求极高，所以没有垃圾碎片回收机制，对于内存的释放要特别小心）。
传统的指针（裸指针 raw pointer）在使用时需要手动分配和释放内存，容易出现内存泄漏和悬挂指针等问题。智能指针通过封装裸指针，并提供自动内存管理功能，使得内存资源可以更安全、高效地管理。</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
<div class="paragraph">
<p>悬挂指针（dangling pointer）是一个指向曾经存在的对象但是该对象已经被销毁的指针。悬挂指针通常发生在以下几种情况中：</p>
</div>
<div class="paragraph">
<p>动态分配的内存被释放后，但指针没有被设置为 nullptr。
指向局部变量的指针在变量离开其作用域后仍然被使用。
指向数组元素的指针在数组被销毁后仍然被使用。</p>
</div>
<div class="paragraph">
<p>悬挂指针是非常危险的，因为尽管指针本身仍然存在，但它所指向的内存可能已经被操作系统重新分配给其他变量或对象，或者已经被清空。尝试通过悬挂指针访问内存可能导致不可预知的行为，包括程序崩溃、数据损坏或安全漏洞。</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>C 里面有四个智能指针：auto_ptr、share_ptr、unique_ptr、weak_ptr。其中后三个是C11支持的，并且第一个已经在 C++11 弃用
它们的特点：</p>
</div>
<div class="paragraph">
<p>（1）unique_ptr 独占对象的所有权，由于没有引用计数，性能较好。
（2）share_ptr 共享对象的所有权，但性能略差。
（3）weak_ptr 配合 share_ptr，解决循环引用问题。</p>
</div>
<div class="paragraph">
<p>unique_ptr 是一个独占型的智能指针，它不允许其他的智能指针共享其内部的指针，不允许通过赋值将一个 unique_ptr 赋值给另一个 unique_ptr。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-cpp" data-lang="cpp">#include &lt;memory&gt;

std::unique_ptr&lt;int&gt; objUP(new int(10));
std::cout &lt;&lt; *objUP &lt;&lt; std::endl;
std::unique_ptr&lt;int&gt; objUP2 = objUP; // std::unique_ptr删除了拷贝构造函数以便禁用复制，编译报错</code></pre>
</div>
</div>
<div class="paragraph">
<p>指定删除器删除</p>
</div>
<div class="paragraph">
<p>shared_ptr 共享被管理的对象，同一时刻可以有多个shared_ptr拥有对象的所有权，当最后一个shared_ptr对象销毁时，被管理对象自动销毁。
简单的说，shared_ptr 实现包含了两个部分：
（1）一个指向堆上创建的对象的裸指针 raw_ptr。
（2）一个指向内部隐藏的、共享的管理对象 shared_count_object。其中use_count是当前这个堆上对象被多少对象引用了，简单来说就是引用计数。</p>
</div>
<div class="imageblock">
<div class="content">
<img src="images/images/shared_ptr.png" alt="shared ptr">
</div>
</div>
<div class="paragraph">
<p>shared_ptr内部包含两个指针，一个指向对象，一个指向控制块。控制块包含一个引用计数、一个弱计数和其他数据（比如删除器、分配器等）。</p>
</div>
<div class="paragraph">
<p>weak_ptr不是用来管理资源的释放的，它主要是用来解决shared_ptr的循环引用问题的。</p>
</div>
<div class="paragraph">
<p>weak_ptr支持用shared_ptr对象来构造weak_ptr对象，构造出来的weak_ptr对象与shared_ptr对象管理同一个资源，但不会增加这块资源对应的引用计数
A引用B，B引用A</p>
</div>
<div class="paragraph">
<p>RAII
RAII（Resource Acquisition Is Initialization，资源获取就是初始化）是一种利用对象生命周期来控制程序资源（如内存、文件句柄、互斥量等等）的简单技术。</p>
</div>
<div class="paragraph">
<p>在对象构造时获取资源，接着控制对资源的访问使之在对象的生命周期内始终保存有效，最后在对象析构时释放资源。借此，我们实际上把管理一份资源的责任托管给了一个对象，好处：</p>
</div>
<div class="paragraph">
<p>不需要显式地释放资源
采用这种方式，对象所需的资源在其生命周期内始终保持有效</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_引用类型">2.2. 引用类型</h3>
<div class="sect3">
<h4 id="_引用概念理解">2.2.1. 引用概念理解</h4>
<div class="paragraph">
<p>引用(referebce)在概念上可以理解为原始变量的一个别名，一旦定义了原始变量的一个引用，后续针对该引用的任何操作，都等价于操作原始变量本身
1) 赋值操作，修改的是原始变量的值
2) 取值操作，获取的是原始变量的值
3) 取地址操作，获取的是原始变量的值</p>
</div>
<div class="paragraph">
<p>引用必须在声明的同时被初始化，之后不能再指向其他变量。</p>
</div>
<div class="paragraph">
<p>只读引用（const 引用），无法修改其引用的原始变量</p>
</div>
<div class="paragraph">
<p>使用一个右值初始化</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>const int&amp; refConst = 100;         // 使用右值初始化只读引用
// error: assignment of read-only reference refConst
// 给一个只读引用赋值，编译错误
// refConst = 200;</code></pre>
</div>
</div>
<div class="paragraph">
<p>使用可修改左值初始化</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>int iValue;
const int&amp; refConst = iValue;    // 使用可修改左值初始化 只读引用
// error: assignment of read-only reference refConst
// 给一个只读引用赋值，编译错误
// refConst = 200;</code></pre>
</div>
</div>
<div class="paragraph">
<p>使用只读左值初始化</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>const int iValue;
const int&amp; refConst = iValue;    // 使用可修改左值初始化 只读引用
// error: assignment of read-only reference refConst
// 给一个只读引用赋值，编译错误
// refConst = 200;</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_指针和引用的区别">2.2.2. 指针和引用的区别</h4>
<div class="paragraph">
<p>有了指针，C++为什么还引入引用这种类型？</p>
</div>
<div class="paragraph">
<p>指针过于灵活，在使用上稍不注意便会引入一些安全隐患</p>
</div>
<div class="paragraph">
<p>引用要求在定义的时候就必须进行初始化，和一个已经存在的对象进行绑定，且之后不能再和其他对象绑定。该特性可以解决解决一些指针使用过程中的安全性问题，例如，使用未初始化的指针（野指针 dangling pointers），对空指针解引用等</p>
</div>
<div class="literalblock">
<div class="content">
<pre>但是依然没有解决使用释放后的内存也没有解决（Use-After-free）</pre>
</div>
</div>
<div class="paragraph">
<p>使用引用可以避免显式地解引用指针，这使得代码更简洁、更易读。例如，通过引用传递参数可以避免在函数内部使用 * 操作符</p>
</div>
<div class="paragraph">
<p>引用是对象的别名，这意味着引用和它所引用的对象在内存中是相同的（这句话有点问题？？）。这有助于在某些情况下提高代码的效率，因为编译器可以优化掉一些不必要的间接访问。</p>
</div>
<div class="paragraph">
<p>在某些情况下，你仍然需要使用指针，比如当你需要动态分配内存、处理数组、操作多态类型或表示可选值时。引用和指针可以协同工作，以提供最大的灵活性和安全性。</p>
</div>
<div class="paragraph">
<p>汇编指令下，观察指针和引用的区别</p>
</div>
<div class="imageblock">
<div class="content">
<img src="images/images/pointer_reference.png" alt="pointer reference">
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>int test_pointer()
{
    int iValue = 0xa;
    int *piValue = &amp;iValue;

    *piValue = 0xb;

    int *piOrg = &amp;iValue;
    int **piPtr = &amp;piValue;

    return *piValue;
}

int test_reference()
{
    int iValue = 0xa;
    int &amp;refValue = iValue;

    refValue = 0xb;

    int *piOrg = &amp;iValue;
    int *piRef = &amp;refValue;

    return refValue;
}

0000000000000806 &lt;_Z14test_referencev&gt;:
 806:   55                      push   %rbp
 807:   48 89 e5                mov    %rsp,%rbp
 80a:   48 83 ec 30             sub    $0x30,%rsp
 80e:   64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
 815:   00 00
 817:   48 89 45 f8             mov    %rax,-0x8(%rbp)
 81b:   31 c0                   xor    %eax,%eax

 int iValue = 0xa; // 定义变量 iValue，内存地址 -0x24(%rbp)
 81d:   c7 45 dc 0a 00 00 00    movl   $0xa,-0x24(%rbp)

 int &amp;refValue = iValue; // 定义引用变量 refValue，内存地址 -0x20(%rbp)
 824:   48 8d 45 dc             lea    -0x24(%rbp),%rax     // 取变量 iValue 的内存地址
 828:   48 89 45 e0             mov    %rax,-0x20(%rbp)     // 将变量 iValue 的内存地址放入引用变量 refValue 的内存中

 refValue = 0xb;
 82c:   48 8b 45 e0             mov    -0x20(%rbp),%rax     // 获取引用变量 refValue 的值（变量 iValue 的内存地址）
 830:   c7 00 0b 00 00 00       movl   $0xb,(%rax)          // 将 0xb 存入 变量 iValue 的地址

 int *piOrg = &amp;iValue;  // 定义指针变量，内存地址为 -0x18(%rbp)，初始化为变量 iValue 的内存地址，
 836:   48 8d 45 dc             lea    -0x24(%rbp),%rax    // 取变量 iValue 的内存地址
 83a:   48 89 45 e8             mov    %rax,-0x18(%rbp)    // 将变量 iValue 的内存地址放入指针变量 piOrg 的内存中

 int *piRef = &amp;refValue; // 定义指针变量，内存地址为 -0x10(%rbp)
 83e:   48 8b 45 e0             mov    -0x20(%rbp),%rax    // 获取引用变量 refValue 的值（变量 iValue 的内存地址）
 842:   48 89 45 f0             mov    %rax,-0x10(%rbp)    // 将变量 iValue 的内存地址放入指针变量 piRef 的内存中

 846:   48 8b 45 e0             mov    -0x20(%rbp),%rax
 84a:   8b 00                   mov    (%rax),%eax
 84c:   48 8b 55 f8             mov    -0x8(%rbp),%rdx
 850:   64 48 33 14 25 28 00    xor    %fs:0x28,%rdx
 857:   00 00
 859:   74 05                   je     860 &lt;_Z14test_referencev+0x5a&gt;
 85b:   e8 10 fe ff ff          callq  670 &lt;__stack_chk_fail@plt&gt;
 860:   c9                      leaveq
 861:   c3                      retq</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>引用必须在声明时初始化，而指针不必。</p>
</li>
<li>
<p>引用一旦初始化后就不能再指向其他对象，而指针可以随时指向新的对象。</p>
</li>
<li>
<p>不存在空引用，但存在空指针。</p>
</li>
<li>
<p>对引用执行 sizeof 操作获取的是原始变量的大小，对指针执行 sizeof 操作获取的是指针的大小，32为4字节，64位8字节</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>引用在最终实现上也是一个实际的内存变量，也有自己的内存地址，保存的是原始变量（引用绑定的变量）地址，类似于指针
但是编译器对引用做了一些特殊处理
1）引用必须在声明的同时被初始化，之后不能再指向其他变量。
2）对任何引用变量取地址生成的汇编指令都是获取原始变量的地址。（普通变量取地址操作转换后的汇编指令为lea，引用变量取地址操作转换后的汇编指令为 mov)
== C++ 函数
函数定义基本语法</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>函数返回值  函数名(函数参数列表)
{
    函数体
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_函数重载">2.3. 函数重载</h3>

</div>
<div class="sect2">
<h3 id="_函数内联">2.4. 函数内联</h3>
<div class="paragraph">
<p>C++ 类中的函数
构造函数
    拷贝构造函数
    移动构造函数
析构函数
函数重写(覆盖)
操作符函数</p>
</div>
</div>
<div class="sect2">
<h3 id="_友元函数">2.5. 友元函数</h3>
<div class="paragraph">
<p>友元函数可以直接访问类的私有成员，它是定义在类外部的普通函数，不属于任何类，但需要类的内部声明，声明需要加friend关键字。
友元函数可访问类的私有和保护成员，但不是类的成员函数
友元函数不能用const修饰
友元函数可以在类定义的任何地方声明，不受类访问限定符限制
一个函数可以是多个类的友元函数
友元函数的调用与普通函数的调用原理相同</p>
</div>
<div class="paragraph">
<p>友元提供了一种突破封装的方式，有时提供了便利。但友元会增加耦合度，破坏了封装，所以友元不宜多用。</p>
</div>
</div>
<div class="sect2">
<h3 id="_回调函数">2.6. 回调函数</h3>
<div class="paragraph">
<p>在复杂的应用程序中，回调函数是经常需要使用的技术。在 C++ 中要实现回调函数有以下几种方式。</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>函数指针</strong></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>这是 C 和 C++ 中处理回调的传统方式。函数指针指向一个函数，然后这个函数可以作为参数传递给另一个函数，并在需要时被调用。
函数指针的定义语法：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>返回类型 (*指针变量名)(参数列表);</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>std::function 类模板</strong>
C+ + 11 引入了 std::function，它是一个通用的、多态的函数封装器，使用类模板实现
std::function 的实例可以对任何可以调用的目标实体进行存储、复制、和调用操作，这些目标实体包括普通函数、Lambda表达式、函数指针、以及其它函数对象等。std::function对象是对C++中现有的可调用实体的一种类型安全的包裹（我们知道像函数指针这类可调用实体，是类型不安全的）。</p>
</li>
<li>
<p><strong>std::bind 函数模板和可调用对象(callable object)</strong></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>std::bind 是一个函数模板，将可调用对象和可调用对象的参数进行绑定，返回新的可调用对象(std::function类型，参数列表可能改变)，返回的新的std::function可调用对象的参数列表根据 bind 函数实参中std::placeholders::_x从小到大对应的参数确定。</p>
</div>
<div class="paragraph">
<p>C++ 引入 std::bind 的意义在于提供了一种灵活的方式来绑定函数或成员函数到一个特定的对象，并设置它们的参数。这种绑定机制在回调函数、线程启动、事件处理等多个场景中都非常有用。</p>
</div>
<div class="paragraph">
<p>bind 第一个参数传入一个函数、函数指针、lamda表达式、类的成员函数都是可以的。</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong> std::invoke </strong></p>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_c_类和对象">3. C++ 类和对象</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre class="highlight"><code></code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>封装
确定公开什么、不公开什么
属性和方法</p>
<div class="ulist">
<ul>
<li>
<p>成员函数</p>
<div class="ulist">
<ul>
<li>
<p>构造函数</p>
</li>
<li>
<p>析构函数</p>
</li>
<li>
<p>虚函数</p>
</li>
</ul>
</div>
</li>
<li>
<p>成员变量</p>
</li>
<li>
<p>静态成员函数</p>
</li>
<li>
<p>静态成员变量</p>
</li>
<li>
<p>访问控制权限
什么公开、什么不公开</p>
<div class="ulist">
<ul>
<li>
<p>public</p>
</li>
<li>
<p>protected</p>
</li>
<li>
<p>private</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>类是现实世界某一类事物的抽象，实例化之后得到具体的对象，对象是类的一个具体实例。</p>
</div>
<div class="ulist">
<ul>
<li>
<p>继承
基类 、父类
派生类、子类</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>公开继承</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>class Derived : public Base
{

};</code></pre>
</div>
</div>
<div class="paragraph">
<p>保护继承</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>class Derived : protected Base
{

};</code></pre>
</div>
</div>
<div class="paragraph">
<p>私有继承</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>class Derived : private Base
{

};</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>多态
=== 虚函数
在C++中，虚函数（virtual function）是面向对象编程中的一个重要概念，它允许在基类中声明一个函数，然后在派生类中重新定义（或覆盖 override）它。通过虚函数，基类指针或引用可以调用在派生类中定义的函数版本，从而实现运行时多态性。</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>纯虚函数和抽象类
如果一个类包含至少一个纯虚函数（以 = 0 结尾），则该类被认为是抽象类，不能直接实例化，只包含纯虚函数而没有成员变量的抽象类和Java中的接口（Interface）功能类似。</p>
</div>
<div class="paragraph">
<p>类的内存布局</p>
</div>
<div class="paragraph">
<p>虚函数表和虚函数表指针（vptr）
virtual function table</p>
</div>
<div class="paragraph">
<p>虚析构函数
== C++ 右值和右值引用</p>
</div>
<div class="paragraph">
<p>在C++中，左值（lvalue）和右值（rvalue）是对表达式分类的术语，</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>左值（lvalue）</strong>
左值的最初定义是“在赋值表达式的左侧的值都叫做左值”。然而，在const关键字被添加到了C++语言之后，这一定义就不准确了，并且左值被分成两个子类：可修改的左值和不可修改的左值（const）。</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>左值是指那些有持久存储状态，并且其地址可以被获取的对象。通常，我们可以获取其地址并对它进行取值的表达式就是左值。例如，变量、数组元素、结构体成员、解引用的指针等都是左值。</p>
</div>
<div class="paragraph">
<p>左值既可以放在赋值运算符的左边，也可以放在赋值运算符的右边。但是数组名比较特殊，虽然数组名是左值，但是不能对其进行赋值操作。</p>
</div>
<div class="paragraph">
<p>数组名的说明
数组名称本身通常被视为一个左值，因为它代表了一个对象的内存位置（即数组的首元素）。但是，你不能直接对数组名称进行赋值操作（例如 arrayName = newValue;），因为数组名称不是一个普通的变量，大多数情况下被视为一个指向数组首元素的常量指针。你可以通过下标访问数组元素，并对这些元素进行赋值操作。</p>
</div>
<div class="paragraph">
<p>此外，在某些上下文中（例如与sizeof或&amp;操作符一起使用时），数组名称的行为可能略有不同。例如，sizeof(arrayName)会返回整个数组的大小，而不仅仅是指针的大小。</p>
</div>
<div class="paragraph">
<p>需要注意的是，当你将数组作为函数参数传递时，数组会退化为指向其首元素的指针。在这种情况下，函数内部接收到的只是一个指针，而不是整个数组。</p>
</div>
<div class="paragraph">
<p>总结来说，数组名称在大多数情况下被视为一个左值，但它有一些特殊的行为和限制。</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>右值（rvalue）</strong>
右值是那些临时性的、没有持久存储状态的对象，或者那些即将被销毁的对象。右值通常出现在表达式的结果中，并且不能被取地址。例如，字面量、临时对象、表达式的结果等通常都是右值。
右值只能放在赋值运算符的右边</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>// 10、20 是整型字面量，是右值
int iA = 10;
int iB = 20;

// "Hello World" 字符串字面量，是右值
std::string str = "Hello World";

// iA + iB 临时对象，是右值
int iC = iA + iB;
// iA + 100 临时对象，是右值
int iD = iA + 100;</code></pre>
</div>
</div>
<div class="paragraph">
<p>右值在C98时就指纯右值，即就是临时变量，比如值传递的时拷贝的参数或者函数返回值是一个值时的临时拷贝对象，或者单纯的字面值 比如 int a = 5　中的5就是一个右值，而在C11中为了支持移动，又引入了亡值，通常在移动后，移后源对象就会被调用析构函数，因为其中的值已经被转移，亡值这个名称也可以说是很通俗易懂了　比如std::move函数的返回值就是亡值</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>左值引用（lvalue Reference）</strong>
在 C 11之前，C 中只存在一种类型的引用，因此它被称为“引用”。但是，在C 11中引入了右值引用之后，引用有时被称为左值引用。左值引用只能用可修改的左值初始化。
左值引用就是对左值的引用。在C中，我们通常使用的引用类型就是左值引用。左值引用在初始化时必须绑定到一个左值上。</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>C++ 定义左值引用的解决的问题
函数传参：实参传给形参时，可以减少拷贝，类似于指针
函数返回值：只要是出了作用域还存在的对象，那么就可以减少拷贝</p>
</div>
<div class="paragraph">
<p>左值非const引用 只能引用可以修改的左值
左值 const 引用，可以引用可以修改的左值，也可以引用不可修改的左值以及右值</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>右值引用（rvalue Reference）</strong>
右值引用就是对右值的引用，使用 &amp;&amp; 语法，只能用右值进行初始化。右值引用在C++11中引入，主要用于支持移动语义，允许程序员编写函数，能够接收并“窃取”资源（如动态分配的内存）从一个即将销毁的对象，而不是复制它。</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>C++ 语法上是支持定义常量右值引用的，例如：
const int&amp;&amp; a = 10;//编译器不会报错
但这种定义出来的右值引用并无实际用处。一方面，右值引用主要用于移动语义和完美转发，其中前者需要有修改右值的权限；其次，常量右值引用的作用就是引用一个不可修改的右值，这项工作完全可以交给常量左值引用完成。</p>
</div>
<div class="paragraph">
<p>右值引用有两个有用的属性。
首先，右值引用将它们初始化的对象的生命周期延长到右值引用的生命周期（对const对象的左值引用也可以这样做）。
其次，非常量右值引用允许您修改右值！</p>
</div>
<div class="paragraph">
<p>C 引入右值引用的原因
C引入右值引用的主要原因在于解决两个问题：实现移动语义和支持函数参数的完美转发。</p>
</div>
<div class="paragraph">
<p>实现移动语义：在C++中，传统的拷贝构造函数和赋值运算符会进行深拷贝，即创建一个新的对象并将源对象的所有数据复制到新对象中。这在某些情况下可能会导致不必要的性能开销，尤其是当处理大型对象或资源密集型对象时。右值引用通过移动语义（Move Semantics）解决了这个问题。移动语义允许我们从一个临时对象（右值）中获取资源，并将其转移到另一个对象中，而不是进行深拷贝。这样，我们就可以避免不必要的拷贝操作，从而提高程序的性能。
移动拷贝构造函数和移动赋值运算符通过右值引用参数接收临时对象，并将其资源（如动态分配的内存、文件句柄等）的所有权转移到新创建的对象上。这通常涉及修改源对象的状态，使其处于有效但未定义的状态，因为资源已经被移动。</p>
</div>
<div class="paragraph">
<p>支持函数参数的完美转发：在C中，模板函数经常需要将其参数无损地转发给其他函数。然而，传统的值传递和引用传递方式在转发参数时可能会改变参数的类型或值。右值引用和完美转发机制允许模板函数将其参数（无论是左值还是右值）原封不动地转发给其他函数，从而保持了参数的原始类型和值。这使得编写通用包装器、代理和委托等变得更加容易。
总的来说，C引入右值引用是为了提高程序的性能、减少不必要的资源拷贝，并支持更灵活的函数参数转发机制。这些特性使得C++在处理大型对象、资源密集型对象和编写通用代码时更加高效和灵活。</p>
</div>
<div class="literalblock">
<div class="content">
<pre> C++左值引用和右值引用
引用类型	可以引用的值类型	使用场景
非常量左值	常量左值	非常量右值	常量右值
非常量左值引用	Y	N	N	N	函数参数、返回值等
常量左值引用	Y	Y	Y	Y	常用于类中构建拷贝构造函数
非常量右值引用	N	N	Y	N	移动语义、完美转发
常量右值引用	N	N	Y	Y	无实际用途</pre>
</div>
</div>
<div class="paragraph">
<p>表中，Y 表示支持，N 表示不支持。</p>
</div>
<div class="imageblock">
<div class="content">
<img src="images/images/reference-kind.png" alt="reference kind">
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>有持久存储状态对象说明</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>在C++的上下文中，当一个对象或表达式被称为有“持久存储状态”时，它意味着该对象在内存中有固定的、持久的存储位置，并且其生命周期不依赖于任何临时状态或表达式的结果。换句话说，该对象在程序的执行过程中会持续存在，直到其生命周期结束（例如，当它被销毁或超出其作用域时）。

以下是一些有持久存储状态的对象示例：

局部变量：在函数内部声明的变量，只要它们在其作用域内，它们就具有持久的存储状态。
全局变量和静态变量：这些变量在整个程序的执行期间都存在。
动态分配的对象：使用new关键字在堆上分配的对象，直到使用delete释放它们之前，它们都有持久的存储状态。
类的成员变量：类实例的成员变量只要类实例存在，它们就具有持久的存储状态。
相对地，没有持久存储状态的对象通常指的是那些临时性的对象，它们的生命周期仅限于表达式求值期间。这些对象通常作为表达式的结果出现，并且不能被取地址，因为它们不存储在固定的内存位置。例如：

字面量：如整数42或字符串字面量"Hello, world!"。
临时对象：在表达式中创建的、没有命名的对象，如函数调用的返回值或算术表达式的结果。
在C++中，能够获取其地址的对象通常都是有持久存储状态的左值，而那些不能获取地址的对象则是右值。右值引用和移动语义的引入允许程序员更有效地处理这些临时对象，通过“窃取”它们的资源来避免不必要的复制操作，从而提高程序的性能。</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>std::move和移动语义</strong>
std::move 是 C++11 引入的一个函数模板，用于将左值转换为右值引用，从而允许利用移动语义而非拷贝语义来操作对象。
std::move 并不实际移动数据。它只是告诉编译器可以使用移动语义。实际上是否发生移动取决于目标对象是否提供了移动构造函数或移动赋值运算符，以及这些操作是否实际移动了数据。</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>此外，一旦一个对象被 std::move，它通常就处于有效但未定义的状态。这意味着对象仍然可以使用（例如，析构函数仍然可以被安全调用），但其值可能不再有意义。因此，在调用 std::move 后，通常不再使用原始对象，除非对其进行了重新赋值。</p>
</div>
<div class="paragraph">
<p>std::move 常用于资源管理的场景，比如智能指针和容器，在这些场景中，移动操作通常比拷贝操作更高效。</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>std::forward和完美转发</strong>
std::forward 是 C++11 引入的一个模板函数，它用于完美转发（Perfect Forwarding）参数。完美转发允许函数模板将其参数无损地（即保持其值类别——左值或右值）转发给另一个函数。这在编写通用包装器、代理、委托或者实现完美转发构造函数的基类中特别有用。</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>1、不完美转发
所谓完美转发，是指在函数模板中，完全按照模板的参数的类型，将参数传递给函数模板中调用的另一个函数。比如：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>template &lt;typename T&gt;
void IamForwording(T t)
{
    IrunCodeActually(t);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>上面的例子中，IamForwarding是一个转发函数模板。而函数IrunCodeActually则是真正执行代码的目标函数。对于目标函数IrunCodeActually而言，它总是希望转发函数将参数按照传入Iamforwarding时的类型传递（即传入ImaForwarding的是左值对象，IrunCodeActually就能获得左值对象，传入ImaForwarding的是右值对象，IrunCodeActually就能获得右值对象），而不产生额外的开销，就好像转发者不存在一样。</p>
</div>
<div class="paragraph">
<p>在ImaForwarding的参数中使用了最基本类型进行转发，该方法会导致参数在传给IrunCodeActually之前就产生了一次临时对象拷贝。因此这样的转发只能说是正确的转发，谈不上完美。</p>
</div>
<div class="paragraph">
<p>2、完美转发
C++11 标准中规定，通常情况下右值引用形式的参数只能接收右值，不能接收左值。但对于函数模板中使用右值引用语法定义的参数来说，它不再遵守这一规定，既可以接收右值，也可以接收左值（此时的右值引用又被称为“万能引用”）。</p>
</div>
<div class="paragraph">
<p>2.1 C引用折叠
C 引用折叠（Reference Collapsing）是 C++11 标准引入的一个特性，用于处理嵌套引用的情况。引用折叠规则在模板元编程和完美转发等高级技术中发挥着重要作用。</p>
</div>
<div class="paragraph">
<p>引用折叠的规则如下：
T&amp; &amp;、T&amp; &amp;&amp; 和 T&amp;&amp; &amp; 都折叠成 T&amp;：这意味着左值引用的引用或右值引用的左值引用最终都变为左值引用。
T&amp;&amp; &amp;&amp; 折叠成 T&amp;&amp;：右值引用的右值引用最终仍为右值引用。
一旦定义中出现了左值引用，引用折叠总是优先将其折叠为左值引用。</p>
</div>
<div class="paragraph">
<p>这些规则用于处理模板参数推导和完美转发等场景中的复杂引用情况。</p>
</div>
<div class="paragraph">
<p>参考资料
1、c++11：std::forward，完美转发
<a href="https://huaweicloud.csdn.net/6549f4315543f15fea1a2285.html?dp_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MzA5MzQ0OSwiZXhwIjoxNzEzNDMxNzMzLCJpYXQiOjE3MTI4MjY5MzMsInVzZXJuYW1lIjoidGlhbnFpbmdtaW5nIn0.eghzHXlG8KYrRCpR-r7TceRtl3RZJ442fheRrjbPOog" class="bare">https://huaweicloud.csdn.net/6549f4315543f15fea1a2285.html?dp_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MzA5MzQ0OSwiZXhwIjoxNzEzNDMxNzMzLCJpYXQiOjE3MTI4MjY5MzMsInVzZXJuYW1lIjoidGlhbnFpbmdtaW5nIn0.eghzHXlG8KYrRCpR-r7TceRtl3RZJ442fheRrjbPOog</a></p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>移动构造函数和移动复制运算符</strong></p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_c_模板">4. C++ 模板</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li>
<p>C++ 模板（template）是一种强大而灵活的编程工具，使用模板可以帮助我们编写与类型无关的代码，使得代码更通用，复用性更强，提高了软件开发的效率和代码的可维护性。</p>
</li>
<li>
<p>C++ 模板是泛型编程的基础，泛型编程即以一种独立于任何特定类型的方式编写代码，是代码复用的一种技巧。</p>
</li>
<li>
<p>C++ 模板可以定义类模板和函数模板。</p>
</li>
<li>
<p>C++ 模板只是定义了生成类和函数的一种通用方式，并不对应具体的类和函数，模板只有经过实例化之后才能生成特定版本的类或函数，模板实例化过程由编译器根据使用过程种传入的实际参数自动推导完成。</p>
</li>
</ul>
</div>
<div class="sect2">
<h3 id="_类模板">4.1. 类模板</h3>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>template &lt;typename T&gt;
class TemplateClass
{
public:
    // 构造函数
    TemplateClass()
    {

    }

    // 析构函数
    ~TemplateClass()
    {

    }
private:
    T m_Data;
};</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_函数模板">4.2. 函数模板</h3>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>template &lt;typename T&gt;
void TemplateFunc(T&amp; arg)
{

}

template &lt;typename T1, typename T2&gt;
void TemplateFunc(T1&amp; arg1, T2&amp; arg2)
{

}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_模板实例化">4.3. 模板实例化</h3>

</div>
<div class="sect2">
<h3 id="_模板参数">4.4. 模板参数</h3>
<div class="sect3">
<h4 id="_类型模板参数">4.4.1. 类型模板参数</h4>
<div class="paragraph">
<p>由 class 或者 typename 标记的参数，称为类型参数，为模板内部定义可以使用的数据类型，这些类型可以是基础类型，也可以是用户自定义的类型，
甚至可以是模板</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>template&lt;typename T&gt;
T add(T a, T b)
{
    return a + b;
}</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>template &lt;template &lt;typename T&gt; class Thing, typename U, typename V&gt;
class Crab
{

};</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_非类型模板参数">4.4.2. 非类型模板参数</h4>
<div class="paragraph">
<p>就是用一个常量作为类(函数)模板的一个参数，在类(函数)模板中可将该参数当成常量来使用。为模板内部定义可以使用的常量
非类型模板参数是有限制的。通常而言，它们包含以下四种类型：
整数及枚举类型
指针（对象指针或函数指针）
引用（对象引用或函数引用）
指向类对象成员函数的指针</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>template &lt;typename T, size_t MAX_SIZE&gt;
class MyArray
{
    ......
private:
    T m_arrData[MAX_SIZE];
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>调用非类型参数的实参必须是常量表达式，即必须能在编译时计算出结果。
需要注意的是，非类型参数只能是整型、字符型或枚举、指针、引用类型。非类型参数在所有实例中都具有相同的值，而类型参数在不同的实例中具有不同的值。</p>
</div>
</div>
<div class="sect3">
<h4 id="_模板参数默认值">4.4.3. 模板参数默认值</h4>
<div class="paragraph">
<p>可以为模板定义多个模板参数，也可以为模板参数指定默认值</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>template &lt;typename T=int, size_t MAX_SIZE=8&gt;
class MyArray
{
    ......
private:
    T m_arrData[MAX_SIZE];
};</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_可变模板参数">4.4.4. 可变模板参数</h4>
<div class="paragraph">
<p>可以定义参数数量不确定的函数模板和类模板</p>
</div>
</div>
<div class="sect3">
<h4 id="_模板实例化_2">4.4.5. 模板实例化</h4>
<div class="paragraph">
<p>传入实际参数，使用模板的过程，称为模板实例化</p>
</div>
<div class="paragraph">
<p>函数模板实例化
隐式实例化：让编译器根据实参推演模板参数的实际类型
显式实例化：明确指定类型使用函数模板</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>// 隐式实例化
add(1, 2);
add(1.0, 2.0);

// 显式实例化
add&lt;int&gt;(1, 2);
add&lt;double&gt;(1, 2);</code></pre>
</div>
</div>
<div class="paragraph">
<p>类模板实例化</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>MyArray&lt;char, 100&gt; arrChar;
std::vector&lt;double&gt; vecData;</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_c_模板特化">4.5. C++ 模板特化</h3>

</div>
<div class="sect2">
<h3 id="_c_引入模板的意义">4.6. C++ 引入模板的意义</h3>
<div class="paragraph">
<p>用于实现泛型编程，提高代码的复用性</p>
</div>
<div class="paragraph">
<p>增加调试难度，可读性</p>
</div>
</div>
<div class="sect2">
<h3 id="_c_标准模板库stl">4.7. C++ 标准模板库（STL）</h3>

</div>
</div>
</div>
<div class="sect1">
<h2 id="_c_时间库和时间操作">5. C++ 时间库和时间操作</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_stdchrono">5.1. std::chrono</h3>
<div class="paragraph">
<p>std::chrono 是 C++ 标准库中的一个头文件，它提供了一套类型、函数和模板类，用于处理日期和时间。这个库的主要目的是提供一个高分辨率的计时器，用于性能测量，同时也支持对日期和时间的各种操作。</p>
</div>
<div class="paragraph">
<p>std::chrono 中的一些关键组件包括：</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>时间点（Time Points）</strong>：表示从某个固定时间点（通常是 epoch，即 1970 年 1 月 1 日 00:00:00 UTC）开始经过的持续时间。例如，std::chrono::system_clock::now() 返回当前的系统时间点。</p>
</li>
<li>
<p><strong>持续时间（Durations）</strong>：表示两个时间点之间的间隔。例如，std::chrono::seconds(5) 表示 5 秒的持续时间。</p>
</li>
<li>
<p><strong>时钟（Clocks）</strong>：提供获取当前时间点的方式。不同的时钟可能基于不同的系统时间源或具有不同的精度。例如，std::chrono::system_clock 是基于系统时间的，而 std::chrono::high_resolution_clock 提供了高分辨率的时间点，通常用于性能测量。</p>
</li>
<li>
<p><strong>时间单位（Time Units）</strong>：如 std::chrono::hours、std::chrono::minutes、std::chrono::seconds 等，用于表示和转换不同的时间单位。</p>
</li>
</ul>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<div class="paragraph">
<p>std::chrono::system_clock 和 std::chrono::steady_clock 区别</p>
</div>
<div class="paragraph">
<p>std::chrono::system_clock 和 std::chrono::steady_clock 是 C++ 标准库 &lt;chrono&gt; 中定义的两种时钟类型，它们提供了获取时间点的功能，但是各自具有不同的特性和使用场景。</p>
</div>
<div class="ulist">
<ul>
<li>
<p>std::chrono::system_clock
std::chrono::system_clock 是与系统时间相关的时钟。它通常用于获取当前日期和时间，或者用于需要与系统时间同步的场合。</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>system_clock 的特点是它的时间点通常可以从用户处或通过网络协议进行设置，这意味着它的时间值可以被修改。因此，它不适用于测量经过的准确时间，因为它可能会受到用户更改系统时间的影响。</p>
</div>
<div class="paragraph">
<p>你可以使用 system_clock::now() 来获取当前的 system_clock 时间点，并使用 system_clock::to_time_t 或 system_clock::from_time_t 来与 C 风格的 time_t 类型进行转换。</p>
</div>
<div class="ulist">
<ul>
<li>
<p>std::chrono::steady_clock
std::chrono::steady_clock 是一个单调递增的时钟，它不受系统时间调整的影响。它主要用于测量经过的时间，因为它总是保证时间的流逝是恒定的，不会因为系统时间的改变而改变。</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>steady_clock 的特点是它的时间点是单调增加的，从某个固定的时间点开始，不会回退。因此，它非常适合用于性能测量、计时器、等待特定时间间隔等场景。</p>
</div>
<div class="paragraph">
<p>你可以使用 steady_clock::now() 来获取当前的 steady_clock 时间点，并使用 duration_cast 来将两个时间点之间的差值转换为特定的时间单位（如秒、毫秒等）。</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_c_原子操作和无锁编程">6. C++ 原子操作和无锁编程</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_现代计算机系统的现状">6.1. 现代计算机系统的现状</h3>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>计算机硬件系统</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>现代计算机系统比较复杂，有很多种不同的形式存在，例如多处理器系统、多核处理器系统、处理器又有核心独有以及核心共享的多级缓存（会存在缓存一致性问题）。</p>
</div>
<div class="paragraph">
<p>现代CPU执行指令上的优化涉及多个方面，这些优化技术旨在提高CPU的性能和效率。以下是一些主要的优化手段：</p>
</div>
<div class="ulist">
<ul>
<li>
<p>提高主频与指令执行效率：通过提高CPU的主频，可以使其更快地执行指令。此外，指令流水线技术、乱序执行和分支预测等技术也被用于提高指令的执行效率。指令流水线技术允许CPU在不同的时钟周期内执行多个指令的不同部分，从而提高了指令的吞吐量。乱序执行技术则允许CPU在保持结果正确性的前提下，不按程序指定的顺序执行指令，以进一步提高执行速度。分支预测技术则用于预测程序分支的执行路径，以减少分支误预测带来的性能损失。</p>
</li>
<li>
<p>使用缓存：为了减少数据访问延迟，现代CPU使用缓存来存储最近访问的数据。缓存位于CPU和主存之间，访问速度远快于主存。通过将常用数据存储在缓存中，CPU可以更快地获取这些数据，从而提高执行效率。此外，优化数据访问模式，如预取技术，也可以进一步提高缓存的利用率。
减少中断次数：CPU在执行程序时，可能会被外部事件或内部条件中断。过多的中断会打断CPU的执行流程，降低性能。因此，减少CPU被打断的次数是提高性能的关键。这可以通过优化操作系统、驱动程序和应用程序的设计来实现。</p>
</li>
<li>
<p>并行与并发：利用并行与并发技术，可以同时执行多个任务或指令，从而提高整体性能。这可以通过多线程、多核处理器等技术实现。多线程技术允许CPU同时处理多个线程，而多核处理器则提供了多个独立的执行单元，可以并行执行多个任务。</p>
</li>
<li>
<p>指令集优化：指令集的优化对于提高CPU性能至关重要。这包括设计更高效的指令、优化编译器对程序代码的重排以及使用预取技术等。通过减少程序执行时间和CPU资源的使用，指令集优化可以显著提高程序的执行效率。
此外，现代CPU还采用了一系列其他优化技术，如垂直扩展（通过增加单个核心的晶体管数量来提高性能）、资源池化技术（预先分配好资源以减少动态分配的开销）以及SIMD指令集优化等。这些技术共同作用于CPU的执行指令过程，以提供更高的性能和效率。</p>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>编译系统</p>
</li>
</ol>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>现代编译系统往往很智能，为了提高生成代码的质量、性能以及资源利用效率，在生成最终的机器指令（目标代码）时会执行很多优化，以下是一些主要的编译器优化方面：</p>
</div>
<div class="paragraph">
<p>常量折叠与常量传播：编译器会尝试将常量表达式计算为常数值，并在编译时替换相关的常量，以减少运行时计算的开销。</p>
</div>
<div class="paragraph">
<p>死代码消除：编译器会识别和删除永远不会执行的代码，包括未使用的变量和不可达的代码块，以减小可执行文件的大小和加快编译速度。</p>
</div>
<div class="paragraph">
<p>循环优化：编译器可以对循环结构进行优化，如循环展开（将循环体复制多次以减少循环次数）和循环不变式外提（将循环中不变的计算移到循环外）。</p>
</div>
<div class="paragraph">
<p>内联函数：编译器可以尝试将函数调用替换为函数体的直接插入，以减少函数调用的开销。但过度内联可能导致代码膨胀。</p>
</div>
<div class="paragraph">
<p>优化数据访问：编译器可以重新排列代码和数据的布局，以利用局部性原理（时间局部性和空间局部性），减少内存访问延迟，提高缓存利用率。</p>
</div>
<div class="paragraph">
<p>条件优化：编译器会分析条件表达式，并尝试将条件分支合并为更有效的代码，如使用条件移动或查找表来替代分支。</p>
</div>
<div class="paragraph">
<p>寄存器分配：编译器会优化寄存器的使用，将频繁访问的变量存储在寄存器中，以减少对内存的访问。</p>
</div>
<div class="paragraph">
<p>指令选择和指令排列：编译器会选择最适合当前处理器的指令，并对指令进行排列以最小化执行时间和能耗。</p>
</div>
<div class="paragraph">
<p>轮廓分析优化：通过分析程序的运行轮廓（即程序各部分的实际执行频率），编译器可以对热点代码进行更深入的优化。</p>
</div>
<div class="paragraph">
<p>多目标优化：除了优化执行速度，编译器还需要考虑代码大小、功耗、实时响应、内存访问量等多个目标，以平衡各种性能指标。</p>
</div>
<div class="paragraph">
<p>因此在不影响最终结果正确的前提下
编译器在生成最终代码时可以对高级语言编写的代码进行重新排列顺序
CPU 在执行指令的时候也可以乱序执行</p>
</div>
</div>
<div class="sect2">
<h3 id="_什么是原子操作">6.2. 什么是原子操作？</h3>
<div class="paragraph">
<p>原子操作（atomic operation）一般是指不可分割的操作（indivisible operation），操作要么全部完成，要么什么都没做，不存在中间状态</p>
</div>
<div class="paragraph">
<p>指的是不能被编译器或 CPU 拆分或以任何方式重新排序的操作或指令。</p>
</div>
</div>
<div class="sect2">
<h3 id="_为什么需要原子操作">6.3. 为什么需要原子操作？</h3>
<div class="paragraph">
<p>现代计算机系统比较复杂，有很多种不同的形式存在，例如多处理器系统、多核处理器系统、处理器又有核心独有以及核心共享的多级缓存，在这种情况下，一个核心修改了某个变量，其他核心什么时候可见是一个十分严肃的问题。</p>
</div>
<div class="paragraph">
<p>在当前这个追求服务极致性能的时代，使用多线程模式进行设计提高程序性能是一个十分常见的思路，当多个线程之间存在数据共享时，如何在这些线程间实现数据的安全访问是一个必然要面临和必须要解决的问题。</p>
</div>
<div class="paragraph">
<p>锁是一个最先想到的方案，但是，如果共享的数据是一些简单的变量，例如引用计数，序号，使用锁会显得有些大材小用，开销也比较大，此时使用原子操作是一种更合理的方案，使用方便且性能更高。</p>
</div>
<div class="paragraph">
<p>同步访问数据的顺序</p>
</div>
</div>
<div class="sect2">
<h3 id="_原子操作实现原理">6.4. 原子操作实现原理？</h3>
<div class="paragraph">
<p>单核系统和多核系统下，对原子操作的要求有不同吗？</p>
</div>
<div class="paragraph">
<p>内存模型</p>
</div>
<div class="paragraph">
<p>在单核系统下，编译器和处理器的优化虽然可以做到很好的优化，但是但是放在多核环境下常常会引出新的问题来，这时候就必须给编译器和处理器某种提示，告诉某些代码的执行顺序不能被优化。</p>
</div>
</div>
<div class="sect2">
<h3 id="_无锁编程">6.5. 无锁编程</h3>
<div class="paragraph">
<p>在原子操作出现之前，对共享数据的读写可能得到不确定的结果，所以多线程并发编程时要对使用锁机制对共享数据的访问过程进行保护。但锁的申请释放增加了访问共享资源的消耗，且可能引起线程阻塞、锁竞争、死锁、优先级反转、难以调试等问题。</p>
</div>
<div class="paragraph">
<p>现在有了原子操作的支持，对单个基础数据类型的读、写访问可以不用锁保护了，但对于复杂数据类型比如链表，有可能出现多个核心在链表同一位置同时增删节点的情况，这将会导致操作失败或错序。所以我们在对某节点操作前，需要先判断该节点的值是否跟预期的一致，如果一致则进行操作，不一致则更新期望值，这几步操作依然需要实现为一个RMW(Read-Modify-Write)原子操作，这就是前面提到的CAS(Compare And Swap)原子操作，它是无锁编程中最常用的操作。</p>
</div>
<div class="paragraph">
<p>既然无锁编程是为了解决锁机制带来的一些问题而出现的，那么无锁编程就可以理解为不使用锁机制就可保证多线程间原子变量同步的编程。无锁(lock-free)的实现只是将多条指令合并成了一条指令形成一个逻辑完备的最小单元，通过兼容CPU指令执行逻辑形成的一种多线程编程模型。</p>
</div>
<div class="paragraph">
<p>无锁编程是基于原子操作的，对基本原子类型的共享访问由load()与store(val)即可保证其并发同步，对抽象复杂类型的共享访问则需要更复杂的CAS来保证其并发同步，并发访问过程只是不使用锁机制了，但还是可以理解为有锁行为的，其粒度很小，性能更高。对于某个无法实现为一个原子操作的并发访问过程还是需要借助锁机制来实现。</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_c_模板元编程">7. C++ 模板元编程</h2>
<div class="sectionbody">

</div>
</div>
<div class="sect1">
<h2 id="_修改记录">8. 修改记录</h2>
<div class="sectionbody">
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 25%;">
<col style="width: 25%;">
<col style="width: 25%;">
<col style="width: 25%;">
</colgroup>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">版本</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">日期</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">说明</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2024-04-22 16:12:27 +0800
</div>
</div>
</body>
</html>